﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Diagnostics.Contracts;

namespace SimpleIR
{
	/// <summary>
	/// A special class for boxed types.
	/// </summary>
	public sealed class IRBoxedType : IRClassType
	{
		private readonly IRValueType m_boxedvalue;

		private IRMemberField m_boxedfield;

		public IRBoxedType(string tnamespace, string tbasename, TypeQualifiers tqual, IRValueType boxedtype)
			: base(tnamespace, tbasename, tqual)
		{
			Contract.Requires(!String.IsNullOrEmpty(tbasename));
			Contract.Requires(boxedtype != null && ((boxedtype is IRPrimitiveType) | (boxedtype is IRValueType)));

			this.m_boxedvalue = boxedtype;
			this.m_boxedfield = null; //initialized later
		}

		[ContractInvariantMethod]
		private void ObjectInvariant()
		{ Contract.Invariant(this.m_boxedvalue != null && ((this.m_boxedvalue is IRPrimitiveType) | (this.m_boxedvalue is IRValueType))); }

		public override void ProcessBuiltinInfoAsNeeded()
		{
			this.m_boxedfield = this.TypeDescription.AllDefInFields.First((IRMemberField f) => f.FieldType == this.m_boxedvalue);
		}

		public IRValueType BoxedTypeValue
		{ 
			get 
			{
				Contract.Ensures(Contract.Result<IRValueType>() != null);

				return this.m_boxedvalue; 
			} 
		}

		public IRMemberField BoxedValueField
		{
			get
			{
				Contract.Ensures(Contract.Result<IRMemberField>() != null);

				return this.m_boxedfield;
			}
		}
	}

	/// <summary>
	/// This class represents the delegate/lambda types in the program.
	/// </summary>
	public sealed class IRLambdaType : IRClassType
	{
		public IRLambdaType(string tnamespace, string tbasename, TypeQualifiers tqual)
			: base(tnamespace, tbasename, tqual)
		{
			Contract.Requires(!String.IsNullOrEmpty(tbasename));
		}
	}
}
